using System;
using System.Security;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace AnimationPage.ViewModels;

public partial class PasswordEntryViewModel : ViewModelBase
{
    /// <summary>
    /// The label to identify what this value is for
    /// </summary>
    [ObservableProperty] private string? _label;

    /// <summary>
    /// The fake password display string
    /// </summary>
    [ObservableProperty] private string? _fakePassword;

    /// <summary>
    /// The current password hint text
    /// </summary>
    [ObservableProperty] private string? _currentPasswordHintText;

    /// <summary>
    /// The new password hint text
    /// </summary>
    [ObservableProperty] private string? _newPasswordHintText;

    /// <summary>
    /// The confirm password hint text
    /// </summary>
    [ObservableProperty] private string? _confirmPasswordHintText;

    /// <summary>
    /// The current saved password
    /// </summary>
    [ObservableProperty] private SecureString? _currentPassword;

    /// <summary>
    /// The current non-commit edited password
    /// </summary>
    [ObservableProperty] private SecureString? _newPassword;

    /// <summary>
    /// The current non-commit edited confirmed password
    /// </summary>
    [ObservableProperty] private SecureString? _confirmPassword;

    /// <summary>
    /// Indicates if the current text is in edit mode
    /// </summary>
    [ObservableProperty] private bool _editing;

    /// <summary>
    /// Indicates if the current control is pending an update (in progress)
    /// </summary>
    [ObservableProperty] private bool _working;

    /// <summary>
    /// The action to run when saving the text.
    /// Returns true if the commit was successful, or false otherwise.
    /// </summary>
    public Func<Task<bool>>? CommitAction { get; set; }

    #region Constructor

    /// <summary>
    /// Default constructor
    /// </summary>
    public PasswordEntryViewModel()
    {
        // Set default hints
        // TODO: Replace with localization text
        CurrentPasswordHintText = "Current Password";
        NewPasswordHintText = "New Password";
        ConfirmPasswordHintText = "Confirm Password";
    }

    #endregion

    /// <summary>
    /// Puts the control into edit mode
    /// </summary>
    [RelayCommand]
    private void OnEdit()
    {
        // Clear all password
        NewPassword = new SecureString();
        ConfirmPassword = new SecureString();

        // Go into edit mode
        Editing = true;
    }

    /// <summary>
    /// Cancels out of edit mode
    /// </summary>
    [RelayCommand]
    private void OnCancel()
    {
        Editing = false;
    }

    /// <summary>
    /// Commits the content and exits out of edit mode
    /// </summary>
    [RelayCommand]
    private void OnSave()
    {
        // Store the result of a commit call
        var result = default(bool);

        RunCommandAsync(() => Working, async () =>
        {
            // While working, come out of edit mode
            Editing = false;

            // Try and do the work
            result = CommitAction == null ? true : await CommitAction();
        }).ContinueWith(t =>
        {
            // If we succeeded...
            // Nothing to do
            // If we fail...
            if (!result)
            {
                // Go back into edit mode
                Editing = true;
            }
        });
    }
}